{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# The MIT License (MIT)\n",
    "\n",
    "# Copyright (c) 2020, NVIDIA CORPORATION.\n",
    "\n",
    "# Permission is hereby granted, free of charge, to any person obtaining a copy of\n",
    "# this software and associated documentation files (the \"Software\"), to deal in\n",
    "# the Software without restriction, including without limitation the rights to\n",
    "# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\n",
    "# the Software, and to permit persons to whom the Software is furnished to do so,\n",
    "# subject to the following conditions:\n",
    "\n",
    "# The above copyright notice and this permission notice shall be included in all\n",
    "# copies or substantial portions of the Software.\n",
    "\n",
    "# THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n",
    "# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\n",
    "# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\n",
    "# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\n",
    "# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\n",
    "# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Tutorial: Feature Engineering for Recommender Systems\n",
    "\n",
    "# 4. Feature Engineering - Numerical\n",
    "\n",
    "## 4.1. Binning"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import IPython\n",
    "\n",
    "import pandas as pd\n",
    "import cudf\n",
    "import numpy as np\n",
    "import cupy\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "df_train = cudf.read_parquet('./data/train.parquet')\n",
    "df_valid = cudf.read_parquet('./data/valid.parquet')\n",
    "\n",
    "df_train['brand'] = df_train['brand'].fillna('UNKNOWN')\n",
    "df_valid['brand'] = df_valid['brand'].fillna('UNKNOWN')\n",
    "\n",
    "df_train['cat_0'] = df_train['cat_0'].fillna('UNKNOWN')\n",
    "df_valid['cat_0'] = df_valid['cat_0'].fillna('UNKNOWN')\n",
    "\n",
    "df_train['cat_1'] = df_train['cat_1'].fillna('UNKNOWN')\n",
    "df_valid['cat_1'] = df_valid['cat_1'].fillna('UNKNOWN')\n",
    "\n",
    "df_train['cat_2'] = df_train['cat_2'].fillna('UNKNOWN')\n",
    "df_valid['cat_2'] = df_valid['cat_2'].fillna('UNKNOWN')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>event_time</th>\n",
       "      <th>event_type</th>\n",
       "      <th>product_id</th>\n",
       "      <th>brand</th>\n",
       "      <th>price</th>\n",
       "      <th>user_id</th>\n",
       "      <th>user_session</th>\n",
       "      <th>target</th>\n",
       "      <th>cat_0</th>\n",
       "      <th>cat_1</th>\n",
       "      <th>cat_2</th>\n",
       "      <th>cat_3</th>\n",
       "      <th>timestamp</th>\n",
       "      <th>ts_hour</th>\n",
       "      <th>ts_minute</th>\n",
       "      <th>ts_weekday</th>\n",
       "      <th>ts_day</th>\n",
       "      <th>ts_month</th>\n",
       "      <th>ts_year</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>2019-12-01 00:00:28 UTC</td>\n",
       "      <td>cart</td>\n",
       "      <td>17800342</td>\n",
       "      <td>zeta</td>\n",
       "      <td>66.90</td>\n",
       "      <td>550465671</td>\n",
       "      <td>22650a62-2d9c-4151-9f41-2674ec6d32d5</td>\n",
       "      <td>0</td>\n",
       "      <td>computers</td>\n",
       "      <td>desktop</td>\n",
       "      <td>UNKNOWN</td>\n",
       "      <td>&lt;NA&gt;</td>\n",
       "      <td>2019-12-01 00:00:28</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>6</td>\n",
       "      <td>1</td>\n",
       "      <td>12</td>\n",
       "      <td>2019</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>2019-12-01 00:00:39 UTC</td>\n",
       "      <td>cart</td>\n",
       "      <td>3701309</td>\n",
       "      <td>polaris</td>\n",
       "      <td>89.32</td>\n",
       "      <td>543733099</td>\n",
       "      <td>a65116f4-ac53-4a41-ad68-6606788e674c</td>\n",
       "      <td>0</td>\n",
       "      <td>appliances</td>\n",
       "      <td>environment</td>\n",
       "      <td>vacuum</td>\n",
       "      <td>&lt;NA&gt;</td>\n",
       "      <td>2019-12-01 00:00:39</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>6</td>\n",
       "      <td>1</td>\n",
       "      <td>12</td>\n",
       "      <td>2019</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>2019-12-01 00:00:40 UTC</td>\n",
       "      <td>cart</td>\n",
       "      <td>3701309</td>\n",
       "      <td>polaris</td>\n",
       "      <td>89.32</td>\n",
       "      <td>543733099</td>\n",
       "      <td>a65116f4-ac53-4a41-ad68-6606788e674c</td>\n",
       "      <td>0</td>\n",
       "      <td>appliances</td>\n",
       "      <td>environment</td>\n",
       "      <td>vacuum</td>\n",
       "      <td>&lt;NA&gt;</td>\n",
       "      <td>2019-12-01 00:00:40</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>6</td>\n",
       "      <td>1</td>\n",
       "      <td>12</td>\n",
       "      <td>2019</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>2019-12-01 00:00:41 UTC</td>\n",
       "      <td>cart</td>\n",
       "      <td>3701309</td>\n",
       "      <td>polaris</td>\n",
       "      <td>89.32</td>\n",
       "      <td>543733099</td>\n",
       "      <td>a65116f4-ac53-4a41-ad68-6606788e674c</td>\n",
       "      <td>0</td>\n",
       "      <td>appliances</td>\n",
       "      <td>environment</td>\n",
       "      <td>vacuum</td>\n",
       "      <td>&lt;NA&gt;</td>\n",
       "      <td>2019-12-01 00:00:41</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>6</td>\n",
       "      <td>1</td>\n",
       "      <td>12</td>\n",
       "      <td>2019</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>2019-12-01 00:01:56 UTC</td>\n",
       "      <td>cart</td>\n",
       "      <td>1004767</td>\n",
       "      <td>samsung</td>\n",
       "      <td>235.60</td>\n",
       "      <td>579970209</td>\n",
       "      <td>c6946211-ce70-4228-95ce-fd7fccdde63c</td>\n",
       "      <td>0</td>\n",
       "      <td>construction</td>\n",
       "      <td>tools</td>\n",
       "      <td>light</td>\n",
       "      <td>&lt;NA&gt;</td>\n",
       "      <td>2019-12-01 00:01:56</td>\n",
       "      <td>0</td>\n",
       "      <td>1</td>\n",
       "      <td>6</td>\n",
       "      <td>1</td>\n",
       "      <td>12</td>\n",
       "      <td>2019</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                event_time event_type  product_id    brand   price    user_id  \\\n",
       "0  2019-12-01 00:00:28 UTC       cart    17800342     zeta   66.90  550465671   \n",
       "1  2019-12-01 00:00:39 UTC       cart     3701309  polaris   89.32  543733099   \n",
       "2  2019-12-01 00:00:40 UTC       cart     3701309  polaris   89.32  543733099   \n",
       "3  2019-12-01 00:00:41 UTC       cart     3701309  polaris   89.32  543733099   \n",
       "4  2019-12-01 00:01:56 UTC       cart     1004767  samsung  235.60  579970209   \n",
       "\n",
       "                           user_session  target         cat_0        cat_1  \\\n",
       "0  22650a62-2d9c-4151-9f41-2674ec6d32d5       0     computers      desktop   \n",
       "1  a65116f4-ac53-4a41-ad68-6606788e674c       0    appliances  environment   \n",
       "2  a65116f4-ac53-4a41-ad68-6606788e674c       0    appliances  environment   \n",
       "3  a65116f4-ac53-4a41-ad68-6606788e674c       0    appliances  environment   \n",
       "4  c6946211-ce70-4228-95ce-fd7fccdde63c       0  construction        tools   \n",
       "\n",
       "     cat_2 cat_3            timestamp  ts_hour  ts_minute  ts_weekday  ts_day  \\\n",
       "0  UNKNOWN  <NA>  2019-12-01 00:00:28        0          0           6       1   \n",
       "1   vacuum  <NA>  2019-12-01 00:00:39        0          0           6       1   \n",
       "2   vacuum  <NA>  2019-12-01 00:00:40        0          0           6       1   \n",
       "3   vacuum  <NA>  2019-12-01 00:00:41        0          0           6       1   \n",
       "4    light  <NA>  2019-12-01 00:01:56        0          1           6       1   \n",
       "\n",
       "   ts_month  ts_year  \n",
       "0        12     2019  \n",
       "1        12     2019  \n",
       "2        12     2019  \n",
       "3        12     2019  \n",
       "4        12     2019  "
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df_train.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Theory"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<b>*Binning*</b> maps multiple ordinal categorical or numerical features into groups. It is mainly applied to numerical features:\n",
    "<li> prevent overfitting by grouping values together\n",
    "<li> enables us to add some expert knowledge into the model\n",
    "<li> most simple case: binary flags, e.g. features is greater than 0<br><br>\n",
    "Examples:<br>\n",
    "<li> binning weekdays into weekday and weekend\n",
    "<li> binning hours into morning, early afternoon, late afternoon, evening and night\n",
    "<li> binning age into child, adlult and retired"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can take a look on the hour of the day. We can see multiple patterns:\n",
    "<li> 0-3 Night: Low purchase probability \n",
    "<li> 4-7 Early morning: Mid purchase probability\n",
    "<li> 8-14 Morning/Lunch: Higher purchase probability\n",
    "<li> 15-20 Afternoon: Low purchase probability\n",
    "<li> 21-23: Evening: High purchase probability"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead tr th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe thead tr:last-of-type th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr>\n",
       "      <th></th>\n",
       "      <th colspan=\"2\" halign=\"left\">target</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th></th>\n",
       "      <th>count</th>\n",
       "      <th>mean</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>ts_hour</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>58470</td>\n",
       "      <td>0.305319</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>99086</td>\n",
       "      <td>0.252377</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>206718</td>\n",
       "      <td>0.282888</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>386098</td>\n",
       "      <td>0.340300</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>554952</td>\n",
       "      <td>0.372178</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>665547</td>\n",
       "      <td>0.375789</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>729542</td>\n",
       "      <td>0.377133</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>758404</td>\n",
       "      <td>0.383824</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>779388</td>\n",
       "      <td>0.393012</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>779987</td>\n",
       "      <td>0.397358</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "         target          \n",
       "          count      mean\n",
       "ts_hour                  \n",
       "0         58470  0.305319\n",
       "1         99086  0.252377\n",
       "2        206718  0.282888\n",
       "3        386098  0.340300\n",
       "4        554952  0.372178\n",
       "5        665547  0.375789\n",
       "6        729542  0.377133\n",
       "7        758404  0.383824\n",
       "8        779388  0.393012\n",
       "9        779987  0.397358"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df_train[['ts_hour', 'target']].groupby('ts_hour').agg(['count', 'mean']).head(10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "hour = list(range(0,24))\n",
    "hour_bin = [0]*4 + [1]*4 + [2]*7 + [3]*6 + [4]*3\n",
    "\n",
    "data = cudf.DataFrame({\n",
    "    'hour': hour,\n",
    "    'hour_bin': hour_bin,\n",
    "})"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>hour</th>\n",
       "      <th>hour_bin</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>1</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>2</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>3</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>4</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>5</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>6</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>7</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>8</td>\n",
       "      <td>2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>9</td>\n",
       "      <td>2</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   hour  hour_bin\n",
       "0     0         0\n",
       "1     1         0\n",
       "2     2         0\n",
       "3     3         0\n",
       "4     4         1\n",
       "5     5         1\n",
       "6     6         1\n",
       "7     7         1\n",
       "8     8         2\n",
       "9     9         2"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "data.head(10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "df_train = df_train.merge(data, how='left', right_on='hour', left_on='ts_hour')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead tr th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe thead tr:last-of-type th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr>\n",
       "      <th></th>\n",
       "      <th colspan=\"2\" halign=\"left\">target</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th></th>\n",
       "      <th>count</th>\n",
       "      <th>mean</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>hour_bin</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>750372</td>\n",
       "      <td>0.310148</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>2708445</td>\n",
       "      <td>0.377661</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>4979563</td>\n",
       "      <td>0.385930</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>2781837</td>\n",
       "      <td>0.337329</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>241140</td>\n",
       "      <td>0.371942</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "           target          \n",
       "            count      mean\n",
       "hour_bin                   \n",
       "0          750372  0.310148\n",
       "1         2708445  0.377661\n",
       "2         4979563  0.385930\n",
       "3         2781837  0.337329\n",
       "4          241140  0.371942"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df_train[['hour_bin', 'target']].groupby('hour_bin').agg(['count', 'mean'])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Binning the numerical features reduces the cardinality (# of unique values). Therefore, a model can easier learn the relationship to the target variables, as there are more observation per category. In addition, binning prevents overfitting."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Another reason to apply binning is to standardize numeric variables per category group. The datasets provides information about the product category (cat_1) and price information.\n",
    "\n",
    "For example, the headphones and smartphones have a different price distribution.\n",
    "<li> We can probably buy good headphones between $100-$200\n",
    "<li> For a good smartphone, prices are probably in the range of $400-$1200\n",
    "\n",
    "Therefore, the buying behavior should be different depending on the price per category (what is a good deal)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.hist(df_train[df_train['cat_2']=='headphone'].price.to_pandas(), bins=50)\n",
    "plt.show()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYkAAAD4CAYAAAAZ1BptAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8vihELAAAACXBIWXMAAAsTAAALEwEAmpwYAAASZUlEQVR4nO3df6zddX3H8edrRYyZOop0DaHNylz/6UyGeINNZhY3slLwj2LiDP4xOkfsEiHRZEtWtyUYdQkuUTMS1wRHYzFOJP4ITcR1HSMx+wPk4hhQGOMOa2hTaUc7cDHTge/9cT6dh8v53Ht7e3vuvafPR3Jyvuf9/Xx/fO735Lz6+X6/5zRVhSRJo/zCcu+AJGnlMiQkSV2GhCSpy5CQJHUZEpKkrguWeweW2iWXXFKbNm1a7t2QpFXlkUce+c+qWje7PnEhsWnTJqanp5d7NyRpVUnyg1F1TzdJkroMCUlSlyEhSeoyJCRJXYaEJKnLkJAkdRkSkqQuQ0KS1GVISJK6Ju4b1+O0afe3RtYP3/aeMe+JJJ0bjiQkSV2GhCSpy5CQJHUZEpKkrnlDIsnGJA8keTLJoSQfafWPJzma5NH2uG5omY8lmUnydJJrhurbW20mye6h+uVJHmr1rya5sNVf317PtPmblrT3kqQ5LWQk8TLwx1W1BdgK3JxkS5v3uaq6oj3uA2jzbgB+HdgO/E2SNUnWAJ8HrgW2AB8YWs+n27p+DTgF3NTqNwGnWv1zrZ0kaUzmDYmqOlZV32vTPwKeAi6bY5EdwN1V9ZOq+j4wA1zVHjNV9WxV/RS4G9iRJMDvAF9ry+8Drh9a1742/TXg6tZekjQGZ3RNop3ueTvwUCvdkuSxJHuTrG21y4DnhhY70mq9+luA/6qql2fVX7WuNv/F1n72fu1KMp1k+sSJE2fSJUnSHBYcEkneCHwd+GhVvQTsAd4KXAEcAz5zLnZwIarqjqqaqqqpdete81+0SpIWaUEhkeR1DALiy1X1DYCqer6qXqmqnwFfYHA6CeAosHFo8Q2t1qu/AFyU5IJZ9Vetq83/pdZekjQGC7m7KcCdwFNV9dmh+qVDzd4LPNGm9wM3tDuTLgc2A98FHgY2tzuZLmRwcXt/VRXwAPC+tvxO4N6hde1s0+8D/qm1lySNwUJ+u+k3gd8HHk/yaKv9GYO7k64ACjgM/BFAVR1Kcg/wJIM7o26uqlcAktwCHADWAHur6lBb358Cdyf5FPAvDEKJ9vylJDPASQbBIkkak0zaP8ynpqZqenp6LNvq/cDfXPzxP0krUZJHqmpqdt1vXEuSugwJSVKXISFJ6jIkJEldhoQkqcuQkCR1GRKSpC5DQpLUZUhIkroMCUlSlyEhSeoyJCRJXYaEJKnLkJAkdRkSkqQuQ0KS1GVISJK6DAlJUpchIUnqMiQkSV2GhCSpy5CQJHUZEpKkLkNCktRlSEiSugwJSVKXISFJ6jIkJEldhoQkqcuQkCR1zRsSSTYmeSDJk0kOJflIq1+c5GCSZ9rz2lZPktuTzCR5LMmVQ+va2do/k2TnUP0dSR5vy9yeJHNtQ5I0HgsZSbwM/HFVbQG2Ajcn2QLsBu6vqs3A/e01wLXA5vbYBeyBwQc+cCvwTuAq4NahD/09wIeGltve6r1tSJLGYN6QqKpjVfW9Nv0j4CngMmAHsK812wdc36Z3AHfVwIPARUkuBa4BDlbVyao6BRwEtrd5b66qB6uqgLtmrWvUNiRJY3BG1ySSbALeDjwErK+qY23WD4H1bfoy4LmhxY602lz1IyPqzLENSdIYLDgkkrwR+Drw0ap6aXheGwHUEu/bq8y1jSS7kkwnmT5x4sS53A1JOq8sKCSSvI5BQHy5qr7Rys+3U0W05+OtfhTYOLT4hlabq75hRH2ubbxKVd1RVVNVNbVu3bqFdEmStAALubspwJ3AU1X12aFZ+4HTdyjtBO4dqt/Y7nLaCrzYThkdALYlWdsuWG8DDrR5LyXZ2rZ146x1jdqGJGkMLlhAm98Efh94PMmjrfZnwG3APUluAn4AvL/Nuw+4DpgBfgx8EKCqTib5JPBwa/eJqjrZpj8MfBF4A/Dt9mCObUiSxmDekKiqfwbSmX31iPYF3NxZ115g74j6NPC2EfUXRm1DkjQefuNaktS1kNNNWkKbdn9rZP3wbe8Z855I0vwcSUiSugwJSVKXISFJ6jIkJEldhoQkqcuQkCR1GRKSpC5DQpLUZUhIkroMCUlSlyEhSeoyJCRJXYaEJKnLkJAkdRkSkqQuQ0KS1GVISJK6DAlJUpchIUnqMiQkSV2GhCSpy5CQJHUZEpKkLkNCktRlSEiSugwJSVKXISFJ6jIkJEldhoQkqWvekEiyN8nxJE8M1T6e5GiSR9vjuqF5H0syk+TpJNcM1be32kyS3UP1y5M81OpfTXJhq7++vZ5p8zctWa8lSQuykJHEF4HtI+qfq6or2uM+gCRbgBuAX2/L/E2SNUnWAJ8HrgW2AB9obQE+3db1a8Ap4KZWvwk41eqfa+0kSWM0b0hU1XeAkwtc3w7g7qr6SVV9H5gBrmqPmap6tqp+CtwN7EgS4HeAr7Xl9wHXD61rX5v+GnB1ay9JGpOzuSZxS5LH2umota12GfDcUJsjrdarvwX4r6p6eVb9Vetq819s7V8jya4k00mmT5w4cRZdkiQNW2xI7AHeClwBHAM+s1Q7tBhVdUdVTVXV1Lp165ZzVyRpoiwqJKrq+ap6pap+BnyBwekkgKPAxqGmG1qtV38BuCjJBbPqr1pXm/9Lrb0kaUwWFRJJLh16+V7g9J1P+4Eb2p1JlwObge8CDwOb251MFzK4uL2/qgp4AHhfW34ncO/Quna26fcB/9TaS5LG5IL5GiT5CvBu4JIkR4BbgXcnuQIo4DDwRwBVdSjJPcCTwMvAzVX1SlvPLcABYA2wt6oOtU38KXB3kk8B/wLc2ep3Al9KMsPgwvkNZ9tZSdKZmTckquoDI8p3jqidbv+XwF+OqN8H3Dei/iw/P101XP8f4Pfm2z9J0rnjN64lSV2GhCSpy5CQJHUZEpKkLkNCktRlSEiSugwJSVKXISFJ6jIkJEldhoQkqcuQkCR1zfvbTRqPTbu/NbJ++Lb3jHlPJOnnHElIkroMCUlSlyEhSeoyJCRJXYaEJKnLkJAkdRkSkqQuQ0KS1GVISJK6DAlJUpchIUnqMiQkSV2GhCSpy5CQJHUZEpKkLkNCktRlSEiSugwJSVKXISFJ6po3JJLsTXI8yRNDtYuTHEzyTHte2+pJcnuSmSSPJblyaJmdrf0zSXYO1d+R5PG2zO1JMtc2JEnjs5CRxBeB7bNqu4H7q2ozcH97DXAtsLk9dgF7YPCBD9wKvBO4Crh16EN/D/ChoeW2z7MNSdKYzBsSVfUd4OSs8g5gX5veB1w/VL+rBh4ELkpyKXANcLCqTlbVKeAgsL3Ne3NVPVhVBdw1a12jtiFJGpPFXpNYX1XH2vQPgfVt+jLguaF2R1ptrvqREfW5tvEaSXYlmU4yfeLEiUV0R5I0yllfuG4jgFqCfVn0NqrqjqqaqqqpdevWnctdkaTzymJD4vl2qoj2fLzVjwIbh9ptaLW56htG1OfahiRpTBYbEvuB03co7QTuHarf2O5y2gq82E4ZHQC2JVnbLlhvAw60eS8l2druarpx1rpGbUOSNCYXzNcgyVeAdwOXJDnC4C6l24B7ktwE/AB4f2t+H3AdMAP8GPggQFWdTPJJ4OHW7hNVdfpi+IcZ3EH1BuDb7cEc25Akjcm8IVFVH+jMunpE2wJu7qxnL7B3RH0aeNuI+gujtiFJGh+/cS1J6jIkJEldhoQkqcuQkCR1GRKSpC5DQpLUZUhIkroMCUlSlyEhSeoyJCRJXYaEJKnLkJAkdRkSkqQuQ0KS1GVISJK6DAlJUpchIUnqMiQkSV2GhCSpy5CQJHUZEpKkLkNCktRlSEiSugwJSVKXISFJ6jIkJEldFyz3Dkjnyqbd3xpZP3zbe8a8J9Lq5UhCktTlSELnlP+al1Y3RxKSpC5HElo1HJVI43dWIZHkMPAj4BXg5aqaSnIx8FVgE3AYeH9VnUoS4K+B64AfA39QVd9r69kJ/EVb7aeqal+rvwP4IvAG4D7gI1VVZ7PPk8IPTEnjsBSnm367qq6oqqn2ejdwf1VtBu5vrwGuBTa3xy5gD0ALlVuBdwJXAbcmWduW2QN8aGi57Uuwv5KkBToX1yR2APva9D7g+qH6XTXwIHBRkkuBa4CDVXWyqk4BB4Htbd6bq+rBNnq4a2hdkqQxONuQKOAfkjySZFerra+qY236h8D6Nn0Z8NzQskdaba76kRH110iyK8l0kukTJ06cTX8kSUPO9sL1u6rqaJJfBg4m+bfhmVVVSc75NYSqugO4A2BqamrJt9c7/y9Jk+6sRhJVdbQ9Hwe+yeCawvPtVBHt+XhrfhTYOLT4hlabq75hRF2SNCaLDokkv5jkTaengW3AE8B+YGdrthO4t03vB27MwFbgxXZa6gCwLcnadsF6G3CgzXspydZ2Z9SNQ+uSJI3B2ZxuWg98c/D5zQXA31XV3yd5GLgnyU3AD4D3t/b3Mbj9dYbBLbAfBKiqk0k+CTzc2n2iqk626Q/z81tgv90e5xVPdUlaTosOiap6FviNEfUXgKtH1Au4ubOuvcDeEfVp4G2L3UdJ0tnxG9da9RxtSeeOIaGR/Ea3JPAH/iRJc3AkMWEcAUhaSobEecLwkLQYnm6SJHUZEpKkLk83aVnMdduqp8CklcORhCSpy5CQJHUZEpKkLkNCktRlSEiSugwJSVKXISFJ6vJ7Euc5f2Z7+fmdEa1kjiQkSV2GhCSpy5CQJHUZEpKkLkNCktRlSEiSurwFVmfE/+FuvJbr7+1x1mmOJCRJXY4kdN7xX8nSwhkSWhJ+c1uaTIaEVpxJDZxJ7ZcmmyEhNZ6Gkl7LkJDmMQnh4ShGi+XdTZKkLkcS0iIt5whjEkY3Wh1WfEgk2Q78NbAG+Nuquu1cbcshuVa7c/0eNpzOPys6JJKsAT4P/C5wBHg4yf6qenJ590zSMMNjcq3okACuAmaq6lmAJHcDOwBDQiuWI9LFW0zYnOnf2+A6Mys9JC4Dnht6fQR45+xGSXYBu9rL/07y9CK3dwnwn4tcdjU6n/prX5dBPj2W9ZxRf5dqn5bJuTy2vzKquNJDYkGq6g7gjrNdT5Lpqppagl1aFc6n/trXyXU+9Xc5+rrSb4E9Cmwcer2h1SRJY7DSQ+JhYHOSy5NcCNwA7F/mfZKk88aKPt1UVS8nuQU4wOAW2L1VdegcbvKsT1mtMudTf+3r5Dqf+jv2vqaqxr1NSdIqsdJPN0mSlpEhIUnqMiSaJNuTPJ1kJsnu5d6fpZDkcJLHkzyaZLrVLk5yMMkz7XltqyfJ7a3/jyW5cnn3fn5J9iY5nuSJodoZ9y/Jztb+mSQ7l6Mv8+n09eNJjrbj+2iS64bmfaz19ekk1wzVV/z7PMnGJA8keTLJoSQfafWJO7Zz9HXlHNuqOu8fDC6K/wfwq8CFwL8CW5Z7v5agX4eBS2bV/grY3aZ3A59u09cB3wYCbAUeWu79X0D/fgu4Enhisf0DLgaebc9r2/Ta5e7bAvv6ceBPRrTd0t7Drwcub+/tNavlfQ5cClzZpt8E/Hvr08Qd2zn6umKOrSOJgf//+Y+q+ilw+uc/JtEOYF+b3gdcP1S/qwYeBC5Kcuky7N+CVdV3gJOzymfav2uAg1V1sqpOAQeB7ed8589Qp689O4C7q+onVfV9YIbBe3xVvM+r6lhVfa9N/wh4isGvL0zcsZ2jrz1jP7aGxMCon/+Y60CtFgX8Q5JH2k+XAKyvqmNt+ofA+jY9KX+DM+3fau/3Le0Uy97Tp1+YoL4m2QS8HXiICT+2s/oKK+TYGhKT7V1VdSVwLXBzkt8anlmD8evE3gM96f0D9gBvBa4AjgGfWda9WWJJ3gh8HfhoVb00PG/Sju2Ivq6YY2tIDEzkz39U1dH2fBz4JoMh6fOnTyO15+Ot+aT8Dc60f6u231X1fFW9UlU/A77A4PjCBPQ1yesYfGh+uaq+0coTeWxH9XUlHVtDYmDifv4jyS8medPpaWAb8ASDfp2+y2MncG+b3g/c2O4U2Qq8ODS0X03OtH8HgG1J1rYh/bZWW/FmXTN6L4PjC4O+3pDk9UkuBzYD32WVvM+TBLgTeKqqPjs0a+KOba+vK+rYLvfV/ZXyYHCHxL8zuEPgz5d7f5agP7/K4A6HfwUOne4T8BbgfuAZ4B+Bi1s9DP6Dp/8AHgemlrsPC+jjVxgMxf+XwTnYmxbTP+APGVwAnAE+uNz9OoO+fqn15bH2gXDpUPs/b319Grh2qL7i3+fAuxicSnoMeLQ9rpvEYztHX1fMsfVnOSRJXZ5ukiR1GRKSpC5DQpLUZUhIkroMCUlSlyEhSeoyJCRJXf8HZQV8Sb801REAAAAASUVORK5CYII=\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.hist(df_train[df_train['cat_1']=='smartphone'].price.to_pandas(), bins=50)\n",
    "plt.show()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Headphones mean price: 316.9701128768166 median price: 189.82\n",
      "Smartphones mean price: 456.3495716886366 median price: 263.84\n"
     ]
    }
   ],
   "source": [
    "print('Headphones mean price: ' + str(df_train[df_train['cat_2']=='headphone'].price.mean()) + ' median price: ' + str(df_train[df_train['cat_2']=='headphone'].price.median()))\n",
    "print('Smartphones mean price: ' + str(df_train[df_train['cat_1']=='smartphone'].price.mean()) + ' median price: ' + str(df_train[df_train['cat_1']=='smartphone'].price.median()))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Based on the category tree, we want to bin the prices as a combination of cat_0, cat_1 and cat_2."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [],
   "source": [
    "df_train['cat_012'] = df_train['cat_0'].astype(str) + '_' + df_train['cat_1'].astype(str) + '_' + df_train['cat_2'].astype(str)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "q_list = [0.1, 0.25, 0.5, 0.75, 0.9]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We calculate the quantiles per category group and then merge the quantile to the original dataframe."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "for q_value in q_list:\n",
    "    q = df_train[['cat_012', 'price']].groupby(['cat_012']).quantile(q_value)\n",
    "    q = q.reset_index()\n",
    "    q.columns = ['cat_012', 'price' + str(q_value)]\n",
    "    df_train = df_train.merge(q, how='left', on='cat_012')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Afterwards, we loop through the columns and update the price_bin depending, if the price is between quantiles."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "df_train['price_bin'] = -1\n",
    "\n",
    "for i, q_value in enumerate(q_list):\n",
    "    if i == 0:\n",
    "        df_train.loc[df_train['price']<=df_train['price' + str(q_value)], 'price_bin'] = i\n",
    "    else:\n",
    "        df_train.loc[(df_train['price']>df_train['price' + str(q_list[i-1])]) & (df_train['price']<=df_train['price' + str(q_value)]), 'price_bin'] = i\n",
    "        \n",
    "df_train.loc[df_train['price']>df_train['price' + str(q_value)], 'price_bin'] = i+1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Example output"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>price</th>\n",
       "      <th>price0.1</th>\n",
       "      <th>price0.25</th>\n",
       "      <th>price0.5</th>\n",
       "      <th>price0.75</th>\n",
       "      <th>price0.9</th>\n",
       "      <th>price_bin</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>1427700</th>\n",
       "      <td>7.61</td>\n",
       "      <td>4.12</td>\n",
       "      <td>5.56</td>\n",
       "      <td>7.60</td>\n",
       "      <td>11.58</td>\n",
       "      <td>16.99</td>\n",
       "      <td>3</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4858449</th>\n",
       "      <td>7.63</td>\n",
       "      <td>4.12</td>\n",
       "      <td>5.56</td>\n",
       "      <td>7.60</td>\n",
       "      <td>11.58</td>\n",
       "      <td>16.99</td>\n",
       "      <td>3</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>449626</th>\n",
       "      <td>7.68</td>\n",
       "      <td>4.12</td>\n",
       "      <td>5.56</td>\n",
       "      <td>7.60</td>\n",
       "      <td>11.58</td>\n",
       "      <td>16.99</td>\n",
       "      <td>3</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>138237</th>\n",
       "      <td>7.70</td>\n",
       "      <td>4.12</td>\n",
       "      <td>5.56</td>\n",
       "      <td>7.60</td>\n",
       "      <td>11.58</td>\n",
       "      <td>16.99</td>\n",
       "      <td>3</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>117511</th>\n",
       "      <td>7.72</td>\n",
       "      <td>3.06</td>\n",
       "      <td>6.15</td>\n",
       "      <td>7.70</td>\n",
       "      <td>12.87</td>\n",
       "      <td>25.71</td>\n",
       "      <td>3</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8098903</th>\n",
       "      <td>766.73</td>\n",
       "      <td>254.81</td>\n",
       "      <td>308.63</td>\n",
       "      <td>514.56</td>\n",
       "      <td>767.81</td>\n",
       "      <td>1283.73</td>\n",
       "      <td>3</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5180578</th>\n",
       "      <td>766.82</td>\n",
       "      <td>254.81</td>\n",
       "      <td>308.63</td>\n",
       "      <td>514.56</td>\n",
       "      <td>767.81</td>\n",
       "      <td>1283.73</td>\n",
       "      <td>3</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9155543</th>\n",
       "      <td>767.05</td>\n",
       "      <td>254.81</td>\n",
       "      <td>308.63</td>\n",
       "      <td>514.56</td>\n",
       "      <td>767.81</td>\n",
       "      <td>1283.73</td>\n",
       "      <td>3</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>941982</th>\n",
       "      <td>767.79</td>\n",
       "      <td>254.81</td>\n",
       "      <td>308.63</td>\n",
       "      <td>514.56</td>\n",
       "      <td>767.81</td>\n",
       "      <td>1283.73</td>\n",
       "      <td>3</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>629787</th>\n",
       "      <td>767.81</td>\n",
       "      <td>254.81</td>\n",
       "      <td>308.63</td>\n",
       "      <td>514.56</td>\n",
       "      <td>767.81</td>\n",
       "      <td>1283.73</td>\n",
       "      <td>3</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>52076 rows × 7 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "          price  price0.1  price0.25  price0.5  price0.75  price0.9  price_bin\n",
       "1427700    7.61      4.12       5.56      7.60      11.58     16.99          3\n",
       "4858449    7.63      4.12       5.56      7.60      11.58     16.99          3\n",
       "449626     7.68      4.12       5.56      7.60      11.58     16.99          3\n",
       "138237     7.70      4.12       5.56      7.60      11.58     16.99          3\n",
       "117511     7.72      3.06       6.15      7.70      12.87     25.71          3\n",
       "...         ...       ...        ...       ...        ...       ...        ...\n",
       "8098903  766.73    254.81     308.63    514.56     767.81   1283.73          3\n",
       "5180578  766.82    254.81     308.63    514.56     767.81   1283.73          3\n",
       "9155543  767.05    254.81     308.63    514.56     767.81   1283.73          3\n",
       "941982   767.79    254.81     308.63    514.56     767.81   1283.73          3\n",
       "629787   767.81    254.81     308.63    514.56     767.81   1283.73          3\n",
       "\n",
       "[52076 rows x 7 columns]"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df_train[df_train['price_bin']==3][['price', 'price0.1', 'price0.25', 'price0.5', 'price0.75', 'price0.9', 'price_bin']].drop_duplicates()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "df_train = df_train.drop(['price' + str(x) for x in q_list])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can see the pattern, that products in a lower quantile 0-10% and 10-25% have lower purchase probabilities."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead tr th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe thead tr:last-of-type th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr>\n",
       "      <th></th>\n",
       "      <th colspan=\"2\" halign=\"left\">target</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th></th>\n",
       "      <th>count</th>\n",
       "      <th>mean</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>price_bin</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>1190744</td>\n",
       "      <td>0.336958</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>1724067</td>\n",
       "      <td>0.359324</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>2844590</td>\n",
       "      <td>0.369048</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>2874795</td>\n",
       "      <td>0.376165</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>1691338</td>\n",
       "      <td>0.375745</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>1135823</td>\n",
       "      <td>0.368033</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "            target          \n",
       "             count      mean\n",
       "price_bin                   \n",
       "0          1190744  0.336958\n",
       "1          1724067  0.359324\n",
       "2          2844590  0.369048\n",
       "3          2874795  0.376165\n",
       "4          1691338  0.375745\n",
       "5          1135823  0.368033"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df_train[['price_bin', 'target']].groupby('price_bin').agg(['count', 'mean'])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Practice"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now, it is your turn. Let's take a look on ts_weekday.<br><br>\n",
    "\n",
    "**ToDo**:\n",
    "<li>Analyze ts_weekday and find a good mapping<br>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "### ToDo"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Optimization"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "cuDF has no native binning function (per groupby) implemented, yet. However, cuDF is constantly developing and new features get implemented. Stay tuned to get the latest updates.<br><br>\n",
    "We can improve our above implementation. Currently, we calculate all binnings and merge them to the original dataframe. That requires more memory. We need only consecutive quantile columns."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We restart the kernel."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'status': 'ok', 'restart': True}"
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "app = IPython.Application.instance()\n",
    "app.kernel.do_shutdown(True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "import IPython\n",
    "\n",
    "import pandas as pd\n",
    "import cudf\n",
    "import numpy as np\n",
    "import cupy\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "df_train = cudf.read_parquet('./data/train.parquet')\n",
    "\n",
    "df_train['brand'] = df_train['brand'].fillna('UNKNOWN')\n",
    "df_train['cat_0'] = df_train['cat_0'].fillna('UNKNOWN')\n",
    "df_train['cat_1'] = df_train['cat_1'].fillna('UNKNOWN')\n",
    "df_train['cat_2'] = df_train['cat_2'].fillna('UNKNOWN')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "df_train['cat_012'] = df_train['cat_0'].astype(str) + '_' + df_train['cat_1'].astype(str) + '_' + df_train['cat_2'].astype(str)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "def group_binning(df, q_list = [0.1, 0.25, 0.5, 0.75, 0.9]):\n",
    "    df['price_bin'] = -1\n",
    "    \n",
    "    for i, q_value in enumerate(q_list):\n",
    "        print(q_value)\n",
    "        q = df[['cat_012', 'price']].groupby(['cat_012']).quantile(q_value)\n",
    "        q = q.reset_index()\n",
    "        q.columns = ['cat_012', 'price' + str(q_value)]\n",
    "        df = df.merge(q, how='left', on='cat_012')\n",
    "        if i == 0:\n",
    "            df.loc[df['price']<=df['price' + str(q_value)], 'price_bin'] = i\n",
    "        else:\n",
    "            df.loc[(df['price']>df['price' + str(q_list[i-1])]) & (df['price']<=df['price' + str(q_value)]), 'price_bin'] = i\n",
    "        if i>=2:\n",
    "            df.drop(['price' + str(q_list[i-2])], axis=1, inplace=True)\n",
    "            \n",
    "    df.loc[df['price']>df['price' + str(q_value)], 'price_bin'] = i+1\n",
    "    df.drop(['price' + str(q_list[i-1])], axis=1, inplace=True)\n",
    "    df.drop(['price' + str(q_list[i])], axis=1, inplace=True)\n",
    "    return(df)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "df_train_pd = df_train.to_pandas()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.1\n",
      "0.25\n",
      "0.5\n",
      "0.75\n",
      "0.9\n",
      "CPU times: user 1min 26s, sys: 41.5 s, total: 2min 8s\n",
      "Wall time: 2min 8s\n"
     ]
    }
   ],
   "source": [
    "%%time\n",
    "\n",
    "df_train_pd = group_binning(df_train_pd)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.1\n",
      "0.25\n",
      "0.5\n",
      "0.75\n",
      "0.9\n",
      "CPU times: user 3.61 s, sys: 3.32 s, total: 6.93 s\n",
      "Wall time: 6.62 s\n"
     ]
    }
   ],
   "source": [
    "%%time\n",
    "\n",
    "df_train = group_binning(df_train)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>event_time</th>\n",
       "      <th>event_type</th>\n",
       "      <th>product_id</th>\n",
       "      <th>brand</th>\n",
       "      <th>price</th>\n",
       "      <th>user_id</th>\n",
       "      <th>user_session</th>\n",
       "      <th>target</th>\n",
       "      <th>cat_0</th>\n",
       "      <th>cat_1</th>\n",
       "      <th>...</th>\n",
       "      <th>cat_3</th>\n",
       "      <th>timestamp</th>\n",
       "      <th>ts_hour</th>\n",
       "      <th>ts_minute</th>\n",
       "      <th>ts_weekday</th>\n",
       "      <th>ts_day</th>\n",
       "      <th>ts_month</th>\n",
       "      <th>ts_year</th>\n",
       "      <th>cat_012</th>\n",
       "      <th>price_bin</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>2019-12-01 07:51:27 UTC</td>\n",
       "      <td>cart</td>\n",
       "      <td>1004781</td>\n",
       "      <td>huawei</td>\n",
       "      <td>247.27</td>\n",
       "      <td>569317987</td>\n",
       "      <td>3c378a32-dd69-4e1b-8251-2cfa0f831cd6</td>\n",
       "      <td>0</td>\n",
       "      <td>construction</td>\n",
       "      <td>tools</td>\n",
       "      <td>...</td>\n",
       "      <td>&lt;NA&gt;</td>\n",
       "      <td>2019-12-01 07:51:27</td>\n",
       "      <td>7</td>\n",
       "      <td>51</td>\n",
       "      <td>6</td>\n",
       "      <td>1</td>\n",
       "      <td>12</td>\n",
       "      <td>2019</td>\n",
       "      <td>construction_tools_light</td>\n",
       "      <td>3</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>2019-12-01 07:51:34 UTC</td>\n",
       "      <td>cart</td>\n",
       "      <td>2401055</td>\n",
       "      <td>turbo</td>\n",
       "      <td>47.88</td>\n",
       "      <td>517451347</td>\n",
       "      <td>d3b2e38b-5d13-4b60-857c-f79f5674686b</td>\n",
       "      <td>0</td>\n",
       "      <td>appliances</td>\n",
       "      <td>kitchen</td>\n",
       "      <td>...</td>\n",
       "      <td>&lt;NA&gt;</td>\n",
       "      <td>2019-12-01 07:51:34</td>\n",
       "      <td>7</td>\n",
       "      <td>51</td>\n",
       "      <td>6</td>\n",
       "      <td>1</td>\n",
       "      <td>12</td>\n",
       "      <td>2019</td>\n",
       "      <td>appliances_kitchen_hood</td>\n",
       "      <td>2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>2019-12-01 07:51:36 UTC</td>\n",
       "      <td>cart</td>\n",
       "      <td>1004856</td>\n",
       "      <td>samsung</td>\n",
       "      <td>124.10</td>\n",
       "      <td>580108461</td>\n",
       "      <td>f272b88b-0dcf-48b8-a466-7398dcda9d3b</td>\n",
       "      <td>0</td>\n",
       "      <td>construction</td>\n",
       "      <td>tools</td>\n",
       "      <td>...</td>\n",
       "      <td>&lt;NA&gt;</td>\n",
       "      <td>2019-12-01 07:51:36</td>\n",
       "      <td>7</td>\n",
       "      <td>51</td>\n",
       "      <td>6</td>\n",
       "      <td>1</td>\n",
       "      <td>12</td>\n",
       "      <td>2019</td>\n",
       "      <td>construction_tools_light</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>2019-12-01 07:51:36 UTC</td>\n",
       "      <td>cart</td>\n",
       "      <td>1004751</td>\n",
       "      <td>samsung</td>\n",
       "      <td>192.77</td>\n",
       "      <td>545521992</td>\n",
       "      <td>686fc0f9-193e-4f81-95ec-02552cd596fe</td>\n",
       "      <td>0</td>\n",
       "      <td>construction</td>\n",
       "      <td>tools</td>\n",
       "      <td>...</td>\n",
       "      <td>&lt;NA&gt;</td>\n",
       "      <td>2019-12-01 07:51:36</td>\n",
       "      <td>7</td>\n",
       "      <td>51</td>\n",
       "      <td>6</td>\n",
       "      <td>1</td>\n",
       "      <td>12</td>\n",
       "      <td>2019</td>\n",
       "      <td>construction_tools_light</td>\n",
       "      <td>2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>2019-12-01 07:51:37 UTC</td>\n",
       "      <td>cart</td>\n",
       "      <td>1801906</td>\n",
       "      <td>tcl</td>\n",
       "      <td>231.13</td>\n",
       "      <td>552287591</td>\n",
       "      <td>681fbfd6-d352-4f3e-8ba6-5219bc0d3071</td>\n",
       "      <td>0</td>\n",
       "      <td>appliances</td>\n",
       "      <td>personal</td>\n",
       "      <td>...</td>\n",
       "      <td>&lt;NA&gt;</td>\n",
       "      <td>2019-12-01 07:51:37</td>\n",
       "      <td>7</td>\n",
       "      <td>51</td>\n",
       "      <td>6</td>\n",
       "      <td>1</td>\n",
       "      <td>12</td>\n",
       "      <td>2019</td>\n",
       "      <td>appliances_personal_massager</td>\n",
       "      <td>2</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>5 rows × 21 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "                event_time event_type  product_id    brand   price    user_id  \\\n",
       "0  2019-12-01 07:51:27 UTC       cart     1004781   huawei  247.27  569317987   \n",
       "1  2019-12-01 07:51:34 UTC       cart     2401055    turbo   47.88  517451347   \n",
       "2  2019-12-01 07:51:36 UTC       cart     1004856  samsung  124.10  580108461   \n",
       "3  2019-12-01 07:51:36 UTC       cart     1004751  samsung  192.77  545521992   \n",
       "4  2019-12-01 07:51:37 UTC       cart     1801906      tcl  231.13  552287591   \n",
       "\n",
       "                           user_session  target         cat_0     cat_1  ...  \\\n",
       "0  3c378a32-dd69-4e1b-8251-2cfa0f831cd6       0  construction     tools  ...   \n",
       "1  d3b2e38b-5d13-4b60-857c-f79f5674686b       0    appliances   kitchen  ...   \n",
       "2  f272b88b-0dcf-48b8-a466-7398dcda9d3b       0  construction     tools  ...   \n",
       "3  686fc0f9-193e-4f81-95ec-02552cd596fe       0  construction     tools  ...   \n",
       "4  681fbfd6-d352-4f3e-8ba6-5219bc0d3071       0    appliances  personal  ...   \n",
       "\n",
       "  cat_3            timestamp ts_hour  ts_minute  ts_weekday  ts_day  ts_month  \\\n",
       "0  <NA>  2019-12-01 07:51:27       7         51           6       1        12   \n",
       "1  <NA>  2019-12-01 07:51:34       7         51           6       1        12   \n",
       "2  <NA>  2019-12-01 07:51:36       7         51           6       1        12   \n",
       "3  <NA>  2019-12-01 07:51:36       7         51           6       1        12   \n",
       "4  <NA>  2019-12-01 07:51:37       7         51           6       1        12   \n",
       "\n",
       "   ts_year                       cat_012 price_bin  \n",
       "0     2019      construction_tools_light         3  \n",
       "1     2019       appliances_kitchen_hood         2  \n",
       "2     2019      construction_tools_light         0  \n",
       "3     2019      construction_tools_light         2  \n",
       "4     2019  appliances_personal_massager         2  \n",
       "\n",
       "[5 rows x 21 columns]"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df_train.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In our experiments, we achieve a speed up of 28.2x."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We shutdown the kernel."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'status': 'ok', 'restart': False}"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "app = IPython.Application.instance()\n",
    "app.kernel.do_shutdown(False)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
